/*
 * Copyright (c) 2009, Hamish Morgan. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the University of Sussex nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package locusts.lib.geom;

import java.awt.Shape;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RectangularShape;
import java.awt.geom.RoundRectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * Utility class to construct complex shapes.
 * 
 * @author Hamish Morgan
 */
public final class Shapes {

    private Shapes() {
    }
//

    public static final double calculateMaxRadius(final Shape s) {
        if (s == null)
            return 0;

        final PathIterator pi = s.getPathIterator(null);
        final double coords[] = new double[6];
        double maxR = 0;
        while (!pi.isDone()) {
            switch (pi.currentSegment(coords)) {

                case PathIterator.SEG_MOVETO:
                case PathIterator.SEG_LINETO:
                    maxR = Math.max(maxR, coords[0]);
                    maxR = Math.max(maxR, coords[1]);
                    break;
//                case PathIterator.SEG_CLOSE:
//                case PathIterator.SEG_QUADTO:
//                case PathIterator.SEG_CUBICTO:
//                default:

            }
            pi.next();
        }
        return maxR;
    }

    public static void writeShape(Shape shape, ObjectOutputStream out) throws
            IOException {

        if (shape instanceof RectangularShape) {
            if (shape instanceof Arc2D) {
                out.writeChar('A');
            } else if (shape instanceof Ellipse2D) {
                out.writeChar('E');
            } else if (shape instanceof Rectangle2D) {
                out.writeChar('R');
            } else if (shape instanceof RoundRectangle2D) {
                out.writeChar('O');
            } else {
                throw new RuntimeException("Can' serialize object: " + shape);
            }

            out.writeDouble(((RectangularShape) shape).getMinX());
            out.writeDouble(((RectangularShape) shape).getMinY());
            out.writeDouble(((RectangularShape) shape).getWidth());
            out.writeDouble(((RectangularShape) shape).getHeight());
            
            if (shape instanceof Arc2D) {
                out.writeDouble(((Arc2D)shape).getAngleStart());
                out.writeDouble(((Arc2D)shape).getAngleExtent());
                out.writeInt(((Arc2D)shape).getArcType());
            } else if (shape instanceof Ellipse2D) {
            } else if (shape instanceof Rectangle2D) {
            } else if (shape instanceof RoundRectangle2D) {
                out.writeDouble(((RoundRectangle2D)shape).getArcWidth());
                out.writeDouble(((RoundRectangle2D)shape).getArcHeight());
            }


        } else {

            throw new RuntimeException("Can' serialize object: " + shape);
        }

    }

    public static Shape readShape(ObjectInputStream in) throws
            IOException {
        final char c = in.readChar();
        final double x0 = in.readDouble();
        final double y0 = in.readDouble();
        final double x1 = in.readDouble();
        final double y1 = in.readDouble();

        if (c == 'R') {
            return new Rectangle2D.Double(x0, y0, y1, y1);
        } else if (c == 'E') {
            return new Ellipse2D.Double(x0, y0, y1, y1);
        } else if (c == 'O') {
            double arcw = in.readDouble();
            double arch = in.readDouble();
            return new RoundRectangle2D.Double(x0, y0, y1, y1, arcw, arch);
        } else if(c == 'A') {
            double start = in.readDouble();;
            double extend = in.readDouble();;
            int type = in.readInt();
            return new Arc2D.Double(x0, y0, x1, y1, start, extend, type);
        }
        return null;
    }

    public static double area(Shape shape) {
        return area(shape.getBounds2D());
    }
    public static double area(Rectangle2D rec) {
        return Math.abs(rec.getWidth() * rec.getHeight());
    }
}
